package com.dong.repeatsubmit.aspect;

import com.dong.repeatsubmit.annotation.NoRepeatSubmit;
import com.dong.repeatsubmit.redis.RedisService;
import com.dong.repeatsubmit.redis.RedissonLockUtil;
import com.dong.repeatsubmit.util.RequestUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

@Aspect
@Component
@Slf4j
public class NoRepeatSubmitAspect {

    @Pointcut("execution(public * com.dong.repeatsubmit.controller..*.*(..))")
    public void pointCut(){

    }

    @Around("pointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {

        // 方法签名
        Signature signature = joinPoint.getSignature();
        // 获取的是代理类的method对象
        Method method = ( (MethodSignature)signature).getMethod();
        // 这个方法才是目标对象上有注解的方法
        Method realMethod = joinPoint.getTarget().getClass().getDeclaredMethod(signature.getName(), method.getParameterTypes());
        Object result = null;
        NoRepeatSubmit repeatSubmit = AnnotationUtils.findAnnotation(realMethod, NoRepeatSubmit.class);
        if (repeatSubmit == null){
            HttpServletRequest request = RequestUtil.getRequest();

            String authorization = request.getHeader("Authorization");
            String path = request.getServletPath();

            String key = authorization + RedisService.JOINER + path + RedisService.JOINER;

            boolean lock = RedissonLockUtil.tryLock(key, true);
            if (lock){
                try {
                    result =  joinPoint.proceed();
                } catch (Throwable throwable) {
                    log.info(throwable.getMessage());
                }finally {
                    RedissonLockUtil.unlock(key,true);
                }
            }else {
                log.info("请勿重复请求");
            }
        }else {
            result =  joinPoint.proceed();
        }
        return result;
    }

}
